package com.chinamsp.dydb.dbsource;

import java.util.HashMap;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.chinamsp.dydb.DydbContstants;


/**
 * 数据源配置
 * @author shifenghu
 *
 */
@ConfigurationProperties(prefix =  DydbContstants.PROPERTIES_PREFIX)
public class DataSourceSettings {


	/**
	 * 扫描的包路径，支持多个，多个用,号分割
	 */
	private String scanPackages;
	
	/**
	 * 默认用户名
	 */
	private String username;
	
	/**
	 * 默认密码
	 */
	private String password;
	
	/**
	 * 数据源类型
	 */
	private String dataSourceTypeName = DATASOURCE_TYPE_DEFAULT;
	
	/**
	 * orm 名称 转换 策略
	 */
	private String ormNameConvertStrategy = DEFAULT_ORM_NAME_STRATEGY;
	
	/**
	 * 驱动名称
	 */
	private String driverClassName = DEFAULT_DRIVER_CLASS_NAME;
	
	/**
	 * 是否开启分库分表检查
	 */
	private boolean enabledShardingChecked = false;
	
	/**
	 * 默认的🐷数据源,如果不设置，则默认 default 
	 */
	private String defaultSource = "default";
	
	/**
	 * 数据源配置
	 */
	private Map<String, DataSourceProperties> resources = new HashMap<>(8);
	
	/**
	 * 默认的 数据库url，主要用于配置默认单个数据源情况
	 */
	private String url;
	
	/**
	 * 其他扩展属性
	 */
	private Map<String, Object> properties; 

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getDriverClassName() {
		return driverClassName;
	}

	public void setDriverClassName(String driverClassName) {
		this.driverClassName = driverClassName;
	}
	
	public String getDefaultSource() {
		return defaultSource;
	}

	public void setDefaultSource(String defaultSource) {
		this.defaultSource = defaultSource;
	}

	public Map<String, DataSourceProperties> getResources() {
		return resources;
	}

	public void setResources(Map<String, DataSourceProperties> resources) {
		this.resources = resources;
	}

	public Map<String, Object> getProperties() {
		return properties;
	}

	public void setProperties(Map<String, Object> properties) {
		this.properties = properties;
	}
	

	public String getOrmNameConvertStrategy() {
		return ormNameConvertStrategy;
	}

	public void setOrmNameConvertStrategy(String ormNameConvertStrategy) {
		this.ormNameConvertStrategy = ormNameConvertStrategy;
	}

	public String getDataSourceTypeName() {
		return dataSourceTypeName;
	}

	public void setDataSourceTypeName(String dataSourceTypeName) {
		this.dataSourceTypeName = dataSourceTypeName;
	}
	

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}
	

	public boolean isEnabledShardingChecked() {
		return enabledShardingChecked;
	}

	public void setEnabledShardingChecked(boolean enabledShardingChecked) {
		this.enabledShardingChecked = enabledShardingChecked;
	}

	
	public String getScanPackages() {
		return scanPackages;
	}

	public void setScanPackages(String scanPackages) {
		this.scanPackages = scanPackages;
	}

	/**
	 * 初始化 数据源
	 * @param dataSourceManager 数据源管理对象
	 */
	public void initialize(DataSourceManager dataSourceManager) {
		// 检查默认用户是否为空
		boolean isEmpty = StringUtils.isEmpty(username);
		// 覆盖下 properties 属性
		this.properties = DefaultDataSourceProperties.merge(driverClassName, properties);
		// 逐个检查
		DataSourceProperties properties;
		for (String key : resources.keySet()) {
			properties = resources.get(key);
			// 检查用户名是否存在
			if (StringUtils.isEmpty(properties.getUsername())) {
				// 如果默认的也没有配置，则直接抛出异常
				if (isEmpty) {
					throw new IllegalArgumentException("[" + key + "]数据源用户名未配置！");
				}
				// 设置默认
				properties.setUsername(username);
				properties.setPassword(password);
			}
			// 检查 从库用户名是否为空，如果为空则设置默认值
			if (StringUtils.isEmpty(properties.getSlaveUsername())) {
				properties.setSlaveUsername(properties.getUsername());
				properties.setSlavePassword(properties.getPassword());
			}
			// 检查 主库的url是否存在
			if (StringUtils.isEmpty(properties.getUrl())) {
				throw new IllegalArgumentException("[" + key + "]数据源主库url未配置！");
			}
			// 设置 默认 driver
			if (StringUtils.isEmpty(properties.getDriverClassName())) {
				properties.setDriverClassName(driverClassName);
			}
			
			// 设置主库
			dataSourceManager.getMasters().put(key, new DataSourceImpl(properties.getUsername(), properties.getPassword(), properties.getUrl(), properties.getDriverClassName(), this.properties));
			// 设置从库
			if (!CollectionUtils.isEmpty(properties.getSlaves())) {
				for (String url : properties.getSlaves()) {
					dataSourceManager.putSalve(key, new DataSourceImpl(properties.getSlaveUsername(), properties.getSlavePassword(), url, properties.getDriverClassName(), this.properties));
				}
			}
		}
		// 如果一个数据源也没有配置，则生成默认数据源
		if (CollectionUtils.isEmpty(resources)) {
			// 检查  url 是否存在
			if (StringUtils.isEmpty(url)) {
				throw new IllegalArgumentException("请至少配置一个数据源");
			}
			properties = new DataSourceProperties();
			properties.setUsername(username);
			properties.setPassword(password);
			properties.setUrl(url);
			properties.setDriverClassName(driverClassName);
			dataSourceManager.getMasters().put(defaultSource, new DataSourceImpl(properties.getUsername(), properties.getPassword(), properties.getUrl(), properties.getDriverClassName(), this.properties));
		}
	}
	
	 private static final String DEFAULT_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
	
	 private static final String DATASOURCE_TYPE_DEFAULT = "com.alibaba.druid.pool.DruidDataSource";
	
	 private static final String DEFAULT_ORM_NAME_STRATEGY = "DefaultNameStrategy";
}
